package com.stylefeng.guns.modular.flagglory.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.common.persistence.dao.GloryUserMapper;
import com.stylefeng.guns.common.persistence.model.*;
import com.stylefeng.guns.core.base.tips.SuccessTip;
import com.stylefeng.guns.core.exception.FrontException;
import com.stylefeng.guns.modular.flagglory.dao.GloryUserDao;
import com.stylefeng.guns.modular.flagglory.service.*;
import com.stylefeng.guns.modular.front.dto.AnswerInfoDto;
import com.stylefeng.guns.modular.front.dto.AnswerResultDto;
import com.stylefeng.guns.modular.front.dto.InfoDto;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * lg_用户 服务实现类
 * </p>
 *
 * @author stylefeng123
 * @since 2018-01-31
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class GloryUserServiceImpl extends ServiceImpl<GloryUserMapper, GloryUser> implements IGloryUserService {
    @Autowired
    private ILevelService levelService;
    @Autowired
    private IDivisionService divisionService;
    @Autowired
    private ISeasonService seasonService;
    @Autowired
    private GloryUserDao gloryUserDao;
    @Autowired
    private IAnswerMirrorService answerMirrorService;
    @Autowired
    private IUserStarService starService;
    @Autowired
    private IQuestionCategoryService questionCategoryService;
    @Autowired
    private IUserRateService userRateService;
    @Autowired
    private IInvitationCodeService codeService;
    @Autowired
    private IDepartmentService departmentService;
    @Autowired
    private ISettingService settingService;

    @Override
    public void register(GloryUser user) throws FrontException {
        EntityWrapper<GloryUser> entityWrapper = new EntityWrapper<>();
        entityWrapper.where("openid='" + user.getOpenid() + "'");
        if (null != selectOne(entityWrapper)) {
            throw new FrontException("该账户已经注册！");
        }
        user.setAuthentication(false);
        EntityWrapper<Level> levelEntityWrapper = new EntityWrapper<>();
        Level level = levelService.selectOne(levelEntityWrapper);
        Season defaultSeason = seasonService.getDefaultSeason();
        user.setLevelid(level.getId());
        UserStar userStar = new UserStar();
        if (!user.insert()) {
            throw new FrontException("注册失败");
        }
        userStar.setUserid(user.getId());
        userStar.setSeasonid(defaultSeason.getId());
        List<QuestionCategory> questionCategories = questionCategoryService.selectList(null);
        for (QuestionCategory category : questionCategories) {
            UserRate userRate = new UserRate();
            userRate.setSeasonid(defaultSeason.getId());
            userRate.setUserid(user.getId());
            userRate.setCategoryid(category.getId());
            userRate.insert();
        }
        if (!userStar.insert()) {
            throw new FrontException("注册失败");
        }
    }

    @Override
    public Map<String, Object> selectGloryUserInfo(String openId) {
        return makeUserInfo(gloryUserDao.selectGloryUserInfo(openId));
    }

    @Override
    public Map<String, Object> selectGloryUserInfo(Integer userId) {
        return makeUserInfo(gloryUserDao.selectGloryUserInfoByUserId(userId));
    }

    private Map<String, Object> makeUserInfo(Map<String, Object> map) {
        int stats = Integer.parseInt(map.getOrDefault("stars", 0).toString());
        int xp = Integer.parseInt(map.getOrDefault("xp", 0).toString());
        //找到当前等级和下一等级
        EntityWrapper<Level> levelEntityWrapper = new EntityWrapper<>();
        levelEntityWrapper.where("xp<=" + xp).orderBy("xp", false);
        Level nowLevel = levelService.selectOne(levelEntityWrapper);
        levelEntityWrapper = new EntityWrapper<>();
        levelEntityWrapper.where("xp>" + xp).orderBy("xp");
        Level nextLevel = levelService.selectOne(levelEntityWrapper);
        if (nextLevel != null) {
            map.put("levelName", nowLevel.getName());
            int lastLevelXp = nextLevel.getXp() - nowLevel.getXp();
            map.put("lastLevelXp", lastLevelXp);
            int leftXp = xp - nowLevel.getXp();
            map.put("xp", leftXp);
            BigDecimal rate = new BigDecimal(leftXp).divide(new BigDecimal(lastLevelXp), 2, BigDecimal.ROUND_HALF_EVEN).multiply(new BigDecimal(100));
            map.put("xpRate", rate.intValue());
        }

        int pDeptId = Integer.parseInt(map.getOrDefault("pdeptid", 0).toString());
        Department pDepartment = departmentService.selectById(pDeptId);
        int total = Integer.parseInt(map.getOrDefault("total", 0).toString());
        int win = Integer.parseInt(map.getOrDefault("win", 0).toString());
        if (total > 1) {
            BigDecimal winB = new BigDecimal(win);
            BigDecimal totalB = new BigDecimal(total);
            BigDecimal winRate = winB.divide(totalB, 2, BigDecimal.ROUND_HALF_EVEN);
            winRate = winRate.multiply(new BigDecimal(100));
            map.put("winRate", winRate.intValue() + "%");
        } else {
            map.put("winRate", "0%");
        }
        Division division = divisionService.getDivision(stats);
        map.put("divisionName", division.getName());
        if (pDepartment != null) {
            map.put("pDeptName", pDepartment.getFullname());
        }
        map.put("divisionId", division.getId());
        map.put("divisionSort", division.getSort());
        return map;
    }

    @Override
    public JSONObject getResult(AnswerResultDto answerResultDto) throws FrontException {
        JSONObject result = new JSONObject();
        Season defaultSeason = seasonService.getDefaultSeason();
        List<AnswerInfoDto> answerInfoDtoList = answerResultDto.getAnswerInfoDtoList();
        Integer userId = answerResultDto.getUserId();
        //段位id
        Integer divisionId = answerResultDto.getDivisionId();
        Integer gameResult = answerResultDto.getGameResult();
        Boolean robot = answerResultDto.getRobot();
        if (divisionId == null || gameResult == null || userId == null) {
            throw new FrontException("参数错误！");
        }
        if (answerInfoDtoList != null && answerInfoDtoList.size() > 0) {
            //如果已经是镜像 就不保存了
            if (robot) {
                //添加镜像信息
                AnswerMirror mirror = new AnswerMirror();
                mirror.setUserid(userId);
                mirror.setSeasonid(defaultSeason.getId());
                mirror.setDivisionid(divisionId);
                mirror.setAnswerinfo(JSONObject.toJSONString(answerInfoDtoList));
                mirror.setCreatetime(new Date());
                answerMirrorService.insert(mirror);
            }
            //添加用户分类答题信息
            for (int i = 0; i < answerInfoDtoList.size(); i++) {
                AnswerInfoDto answerInfoDto = answerInfoDtoList.get(i);
                InfoDto infoDto = answerInfoDto.getInfoDto();
                Integer rightAnswer = infoDto.getRightAnswer();
                Integer selectAnswer = infoDto.getSelected();
                Integer questionCategoryId = answerInfoDto.getCategoryId();
                EntityWrapper<UserRate> userRateEntityWrapper = new EntityWrapper<>();
                userRateEntityWrapper.where("userid=" + userId).and("categoryid=" + questionCategoryId)
                        .and("seasonid=" + defaultSeason.getId());
                UserRate userRate = userRateService.selectOne(userRateEntityWrapper);
                Integer rightnum = userRate.getRightnum();
                Integer totalnum = userRate.getTotalnum();
                userRate.setTotalnum(totalnum + 1);
                if (rightAnswer.equals(selectAnswer)) {
                    userRate.setRightnum(rightnum + 1);
                }
                userRate.updateById();
            }
        }

        GloryUser user = selectById(userId);
        EntityWrapper<UserStar> userStarEntityWrapper = new EntityWrapper<>();
        userStarEntityWrapper.where("userid=" + userId).and("seasonid=" + defaultSeason.getId());
        UserStar userStar = starService.selectOne(userStarEntityWrapper);
        Integer userStarNumber = userStar.getNumber();
        //获取挑战段位信息
        Division division = divisionService.selectById(divisionId);
        //获取用户当前段位
        Division userDivision = divisionService.getDivision(userStarNumber);
        Integer divisionStar = userDivision.getStar();
        //下一个段位的信息
        Division nextDivision = divisionService.getNextDivision(userDivision.getId());
        Integer exp = division.getExp();
        Integer winFlag = division.getWinflag();


        Integer userFlag = user.getFlag();
        //场次相关
        if (gameResult == 0) {
            //胜场得分
            user.setWin(user.getWin() + 1);
            user.setFlag(userFlag + winFlag);
            userStarNumber += 1;
            userStar.setNumber(userStarNumber);
            result.put("winFlag", winFlag);
            result.put("userFlag", userFlag);
        } else if (gameResult == 1) {
            //失败场次得分
            //最多降到当前段位的最低星星
            if (userStarNumber > divisionStar) {
                userStar.setNumber(userStar.getNumber() - 1);
            }
            result.put("winFlag", 0);
            result.put("userFlag", userFlag);
        } else if (gameResult == 2) {
            //平局 返回旗帜 星星不变
            winFlag = division.getFlag();
            user.setFlag(userFlag + winFlag);
            result.put("winFlag", winFlag);
            result.put("userFlag", userFlag);
        }
        //段位信息
        if (null != nextDivision) {
            Integer nextDivisionStar = nextDivision.getStar();
            if (userStarNumber >= nextDivisionStar) {
                result.put("division", nextDivision.getName());
            } else {
                result.put("division", userDivision.getName());
            }
        } else {
            result.put("division", userDivision.getName());
        }

        result.put("star", userStar.getNumber());
        userStar.updateById();
        user.setTotal(user.getTotal() + 1);
        //经验相关
        Integer nowXp = user.getXp() + exp;
        Integer levelId = user.getLevelid();
        EntityWrapper<Level> levelEntityWrapper = new EntityWrapper<>();
        levelEntityWrapper.where("xp<=" + nowXp).orderBy("xp desc");

        Level level = levelService.selectById(levelId);
        //获取当前经验所对应的等级
        Level arriveLevel = levelService.selectOne(levelEntityWrapper);
        //获取下一级所需数据
        levelEntityWrapper = new EntityWrapper<>();
        levelEntityWrapper.where("xp>" + nowXp).orderBy("xp asc");
        Level nextLevel = levelService.selectOne(levelEntityWrapper);
        if (null != nextLevel) {
            result.put("nextLevel", nextLevel.getName());
            result.put("nextLevelExp", nextLevel.getXp());
        } else {
            result.put("nextLevel", "已达满级");
            result.put("nextLevelExp", 0);
        }
        if (!level.getId().equals(arriveLevel.getId())) {
            //升级
            user.setLevelid(arriveLevel.getId());
            result.put("isUpgrade", true);
            result.put("nowLevel", arriveLevel.getName());
        } else {
            result.put("isUpgrade", false);
            result.put("nowLevel", level.getName());
        }
        result.put("userExp", nowXp);
        result.put("exp", exp);
        user.setXp(nowXp);
        updateById(user);
        return result;
    }

    @Override
    public List<Map<String, Object>> selectUserList(Integer deptId) throws FrontException {
        Season defaultSeason = seasonService.getDefaultSeason();
        return gloryUserDao.selectUserList(deptId, defaultSeason.getId());
    }

    @Override
    public void authentication(Integer userId, Integer deptId, String code, String realName) throws Exception {
        if (userId == null || deptId == null || StringUtils.isBlank(realName)) {
            throw new FrontException(500, "请输入正确的内容！");
        }
        Setting isShowModel = settingService.getSetting("is_show_model");
        if (isShowModel == null || !isShowModel.getValue().equals("0")) {
            if (StringUtils.isBlank(code)) {
                throw new FrontException(500, "验证码不能为空！");
            }
            EntityWrapper<InvitationCode> invitationCodeEntityWrapper = new EntityWrapper<>();
            invitationCodeEntityWrapper.where("deptid=" + deptId).and("code='" + code + "'");
            InvitationCode invitationCode = codeService.selectOne(invitationCodeEntityWrapper);
            if (null == invitationCode) {
                throw new FrontException(501, "邀请码错误！请检查选择的部门与邀请码是否正确！");
            }
            if (!invitationCode.getAvailable()) {
                throw new FrontException(501, "该邀请码已被使用！请更换邀请码！");
            }
            invitationCode.setAvailable(false);
            if (!codeService.updateById(invitationCode)) {
                throw new FrontException(500, "验证失败！");
            }
        }
        GloryUser user = selectById(userId);
        if (null == user) {
            throw new Exception("用户不存在！");
        }
        boolean authentication = user.isAuthentication();
        if (authentication) {
            throw new FrontException(501, "该用户已经验证,请勿重复验证！");
        }

        user.setRealname(realName);
        user.setDeptid(deptId);
        user.setAuthentication(true);
        if (!user.updateById()) {
            throw new FrontException("验证失败！");
        }
    }
}
